home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / src / mhitm.c < prev    next >
C/C++ Source or Header  |  1992-12-27  |  27KB  |  1,042 lines

  1. /*    SCCS Id: @(#)mhitm.c    3.1    92/12/10    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6. #include "artifact.h"
  7. #include "edog.h"
  8.  
  9. #ifdef OVLB
  10.  
  11. static boolean NEARDATA vis, NEARDATA far_noise;
  12. static long NEARDATA noisetime;
  13. static struct obj NEARDATA *otmp;
  14.  
  15. static void FDECL(mrustm, (struct monst *, struct monst *, struct obj *));
  16. static int FDECL(hitmm, (struct monst *,struct monst *,struct attack *));
  17. static int FDECL(gazemm, (struct monst *,struct monst *,struct attack *));
  18. static int FDECL(gulpmm, (struct monst *,struct monst *,struct attack *));
  19. static int FDECL(explmm, (struct monst *,struct monst *,struct attack *));
  20. static int FDECL(mdamagem, (struct monst *,struct monst *,struct attack *));
  21. static void FDECL(mswingsm, (struct monst *, struct monst *, struct obj *));
  22. static void FDECL(noises,(struct monst *,struct attack *));
  23. static void FDECL(missmm,(struct monst *,struct monst *,struct attack *));
  24. static int FDECL(passivemm, (struct monst *, struct monst *, BOOLEAN_P, int));
  25.  
  26. /* Needed for the special case of monsters wielding vorpal blades (rare).
  27.  * If we use this a lot it should probably be a parameter to mdamagem()
  28.  * instead of a global variable.
  29.  */
  30. static int dieroll;
  31.  
  32. static void
  33. noises(magr, mattk)
  34.     register struct monst *magr;
  35.     register struct    attack *mattk;
  36. {
  37.     boolean farq = (distu(magr->mx, magr->my) > 15);
  38.  
  39.     if(flags.soundok && (farq != far_noise || moves-noisetime > 10)) {
  40.         far_noise = farq;
  41.         noisetime = moves;
  42.         You("hear %s%s.",
  43.             (mattk->aatyp == AT_EXPL) ? "an explosion" : "some noises",
  44.             farq ? " in the distance" : "");
  45.     }
  46. }
  47.  
  48. static
  49. void
  50. missmm(magr, mdef, mattk)
  51.     register struct monst *magr, *mdef;
  52.     struct attack *mattk;
  53. {
  54.     const char *fmt;
  55.     char buf[BUFSZ];
  56.  
  57.     if (vis) {
  58.         if (mdef->m_ap_type) seemimic(mdef);
  59.         if (magr->m_ap_type) seemimic(magr);
  60.         fmt = (could_seduce(magr,mdef,mattk) && !magr->mcan) ?
  61.             "%s pretends to be friendly to" : "%s misses";
  62.         Sprintf(buf, fmt, Monnam(magr));
  63.         pline("%s %s.", buf, mon_nam(mdef));
  64.     } else  noises(magr, mattk);
  65. }
  66.  
  67. /*
  68.  *  fightm()  -- fight some other monster
  69.  *
  70.  *  Returns:
  71.  *    0 - Monster did nothing.
  72.  *    1 - If the monster made an attack.  The monster might have died.
  73.  *
  74.  *  There is an exception to the above.  If mtmp has the hero swallowed,
  75.  *  then we report that the monster did nothing so it will continue to
  76.  *  digest the hero.
  77.  */
  78. int
  79. fightm(mtmp)        /* have monsters fight each other */
  80.     register struct monst *mtmp;
  81. {
  82.     register struct monst *mon, *nmon;
  83.     int result, has_u_swallowed;
  84. #ifdef LINT
  85.     nmon = 0;
  86. #endif
  87.     /* perhaps the monster will resist Conflict */
  88.     if(resist(mtmp, RING_CLASS, 0, 0))
  89.         return(0);
  90. #ifdef POLYSELF
  91.     if(u.ustuck == mtmp) {
  92.         /* perhaps we're holding it... */
  93.         if(itsstuck(mtmp))
  94.         return(0);
  95.     }
  96. #endif
  97.     has_u_swallowed = (u.uswallow && (mtmp == u.ustuck));
  98.  
  99.     for(mon = fmon; mon; mon = nmon) {
  100.         nmon = mon->nmon;
  101.         if(nmon == mtmp) nmon = mtmp->nmon;
  102.         if(mon != mtmp) {
  103.         if(monnear(mtmp,mon->mx,mon->my)) {
  104.             if(!u.uswallow && (mtmp == u.ustuck)) {
  105.             if(!rn2(4)) {
  106.                 pline("%s releases you!", Monnam(mtmp));
  107.                 u.ustuck = 0;
  108.             } else
  109.                 break;
  110.             }
  111.  
  112.             /* mtmp can be killed */
  113.             bhitpos.x = mon->mx;
  114.             bhitpos.y = mon->my;
  115.             result = mattackm(mtmp,mon);
  116.  
  117.             if (result & MM_AGR_DIED) return 1;    /* mtmp died */
  118.             /*
  119.              *  If mtmp has the hero swallowed, lie and say there
  120.              *  was no attack (this allows mtmp to digest the hero).
  121.              */
  122.             if (has_u_swallowed) return 0;
  123.  
  124.             return ((result & MM_HIT) ? 1 : 0);
  125.         }
  126.         }
  127.     }
  128.     return 0;
  129. }
  130.  
  131. /*
  132.  * mattackm() -- a monster attacks another monster.
  133.  *
  134.  * This function returns a result bitfield:
  135.  *       
  136.  *        --------- agressor died
  137.  *       /  ------- defender died
  138.  *      /  /  ----- defender was hit
  139.  *     /  /  /
  140.  *    x  x  x
  141.  *
  142.  *    0x4    MM_AGR_DIED
  143.  *    0x2    MM_DEF_DIED
  144.  *    0x1    MM_HIT
  145.  *    0x0    MM_MISS
  146.  *
  147.  * Each successive attack has a lower probability of hitting.  Some rely on the
  148.  * success of previous attacks.  ** this doen't seem to be implemented -dl **
  149.  *
  150.  * In the case of exploding monsters, the monster dies as well.
  151.  */
  152. int
  153. mattackm(magr, mdef)
  154.     register struct monst *magr,*mdef;
  155. {
  156.     int            i,        /* loop counter */
  157.             tmp,    /* amour class difference */
  158.             strike,    /* hit this attack */
  159.             attk,    /* attack attempted this time */
  160.             struck = 0,    /* hit at least once */
  161.             res[NATTK];    /* results of all attacks */
  162.     struct attack   *mattk;
  163.     struct permonst *pa, *pd;
  164.  
  165.     if (!magr || !mdef) return(MM_MISS);        /* mike@genat */
  166.     pa = magr->data; pd = mdef->data;
  167.     if (!magr->mcanmove) return(MM_MISS);        /* riv05!a3 */
  168.  
  169.     /* Grid bugs cannot attack at an angle. */
  170.     if (pa == &mons[PM_GRID_BUG] && magr->mx != mdef->mx
  171.                         && magr->my != mdef->my)
  172.     return(MM_MISS);
  173.  
  174.     /* Calculate the armour class differential. */
  175.     tmp = find_mac(mdef) + magr->m_lev;
  176.     if (mdef->mconf || !mdef->mcanmove || mdef->msleep){
  177.     tmp += 4;
  178.     if (mdef->msleep) mdef->msleep = 0;
  179.     }
  180.  
  181.     /* undetect monsters become un-hidden if they are attacked */
  182.     if (mdef->mundetected) {
  183.     mdef->mundetected = 0;
  184.     newsym(mdef->mx, mdef->my);
  185.     if(canseemon(mdef))
  186.         pline("Suddenly, you notice %s.", a_monnam(mdef));
  187.     }
  188.  
  189.     /* Elves hate orcs. */
  190.     if (is_elf(pa) && is_orc(pd)) tmp++;
  191.  
  192.  
  193.     /* Set up the visibility of action */
  194.     vis = (cansee(magr->mx,magr->my) && cansee(mdef->mx,mdef->my));
  195.  
  196.     /*    Set flag indicating monster has moved this turn.  Necessary since a
  197.      *    monster might get an attack out of sequence (i.e. before its move) in
  198.      *    some cases, in which case this still counts as its move for the round
  199.      *    and it shouldn't move again.
  200.      */
  201.     magr->mlstmv = monstermoves;
  202.  
  203.     /* Now perform all attacks for the monster. */
  204.     for (i = 0; i < NATTK; i++) {
  205.     res[i] = MM_MISS;
  206.     mattk = &(pa->mattk[i]);
  207.     otmp = (struct obj *)0;
  208.     attk = 1;
  209.     switch (mattk->aatyp) {
  210.         case AT_WEAP:        /* "hand to hand" attacks */
  211. #ifdef MUSE
  212.         if (magr->weapon_check == NEED_WEAPON || !MON_WEP(magr)) {
  213.             magr->weapon_check = NEED_HTH_WEAPON;
  214.             if (mon_wield_item(magr) != 0) return 0;
  215.         }
  216.         otmp = MON_WEP(magr);
  217. #else
  218.         otmp = select_hwep(magr);
  219. #endif
  220.         if (otmp) {
  221.             if (vis) mswingsm(magr, mdef, otmp);
  222.             tmp += hitval(otmp, pd);
  223.         }
  224.         /* fall through */
  225.         case AT_CLAW:
  226.         case AT_KICK:
  227.         case AT_BITE:
  228.         case AT_STNG:
  229.         case AT_TUCH:
  230.         case AT_BUTT:
  231.         case AT_TENT:
  232.         dieroll = rnd(20 + i);
  233.         strike = (tmp > dieroll);
  234.         if (strike)
  235.             res[i] = hitmm(magr, mdef, mattk);
  236.         else
  237.             missmm(magr, mdef, mattk);
  238.         break;
  239.  
  240.         case AT_HUGS:    /* automatic if prev two attacks succeed */
  241.         strike = (i >= 2 && res[i-1] == MM_HIT && res[i-2] == MM_HIT);
  242.         if (strike)
  243.             res[i] = hitmm(magr, mdef, mattk);
  244.  
  245.         break;
  246.  
  247.         case AT_GAZE:
  248.         strike = 0;    /* will not wake up a sleeper */
  249.         res[i] = gazemm(magr, mdef, mattk);
  250.         break;
  251.  
  252.         case AT_EXPL:
  253.         strike = 1;    /* automatic hit */
  254.         res[i] = explmm(magr, mdef, mattk);
  255.         break;
  256.  
  257.         case AT_ENGL:
  258.         /* Engulfing attacks are directed at the hero if
  259.          * possible. -dlc
  260.          */
  261.         if (u.uswallow && magr == u.ustuck)
  262.             strike = 0;
  263.         else {
  264.             if ((strike = (tmp > rnd(20+i))))
  265.             res[i] = gulpmm(magr, mdef, mattk);
  266.             else
  267.             missmm(magr, mdef, mattk);
  268.         }
  269.         break;
  270.  
  271.         default:        /* no attack */
  272.         strike = 0;
  273.         attk = 0;
  274.         break;
  275.     }
  276.  
  277.     if (attk && !(res[i] & MM_AGR_DIED))
  278.         res[i] = passivemm(magr, mdef, strike, res[i] & MM_DEF_DIED);
  279.  
  280.     if (res[i] & MM_DEF_DIED) return res[i];
  281.  
  282.     /*
  283.      *  Wake up the defender.  NOTE:  this must follow the check
  284.      *  to see if the defender died.  We don't want to modify
  285.      *  unallocated monsters!
  286.      */
  287.     if (strike) mdef->msleep = 0;
  288.  
  289.     if (res[i] & MM_AGR_DIED)  return res[i];
  290.     /* return if aggressor can no longer attack */
  291.     if (!magr->mcanmove || magr->msleep) return res[i];
  292.     if (res[i] & MM_HIT) struck = 1;    /* at least one hit */
  293.     }
  294.  
  295.     return(struck ? MM_HIT : MM_MISS);
  296. }
  297.  
  298. /* Returns the result of mdamagem(). */
  299. static int
  300. hitmm(magr, mdef, mattk)
  301.     register struct monst *magr,*mdef;
  302.     struct    attack *mattk;
  303. {
  304.     if(vis){
  305.         int compat;
  306.         char buf[BUFSZ];
  307.  
  308.         if(mdef->m_ap_type) seemimic(mdef);
  309.         if(magr->m_ap_type) seemimic(magr);
  310.         if((compat = could_seduce(magr,mdef,mattk)) && !magr->mcan) {
  311.             Sprintf(buf, "%s %s", Monnam(magr),
  312.                 mdef->mcansee ? "smiles at" : "talks to");
  313.             pline("%s %s %s.", buf, mon_nam(mdef),
  314.                 compat == 2 ?
  315.                     "engagingly" : "seductively");
  316.         } else {
  317.             char magr_name[BUFSZ];
  318.  
  319.             Strcpy(magr_name, Monnam(magr));
  320.             switch (mattk->aatyp) {
  321.             case AT_BITE:
  322.                 Sprintf(buf,"%s bites", magr_name);
  323.                 break;
  324.             case AT_STNG:
  325.                 Sprintf(buf,"%s stings", magr_name);
  326.                 break;
  327.             case AT_BUTT:
  328.                 Sprintf(buf,"%s butts", magr_name);
  329.                 break;
  330.             case AT_TUCH:
  331.                 Sprintf(buf,"%s touches", magr_name);
  332.                 break;
  333.             case AT_TENT:
  334.                 Sprintf(buf, "%s tentacles suck",
  335.                     s_suffix(magr_name));
  336.                 break;
  337.             case AT_HUGS:
  338.                 if (magr != u.ustuck) {
  339.                     Sprintf(buf,"%s squeezes", magr_name);
  340.                     break;
  341.                 }
  342.             default:
  343.                 Sprintf(buf,"%s hits", magr_name);
  344.             }
  345.         }
  346.         pline("%s %s.", buf, mon_nam(mdef));
  347.     } else  noises(magr, mattk);
  348.     return(mdamagem(magr, mdef, mattk));
  349. }
  350.  
  351. /* Returns the same values as mdamagem(). */
  352. static int
  353. gazemm(magr, mdef, mattk)
  354.     register struct monst *magr, *mdef;
  355.     struct attack *mattk;
  356. {
  357.     char buf[BUFSZ];
  358.  
  359.     if(vis) {
  360.         Sprintf(buf,"%s gazes at", Monnam(magr));
  361.         pline("%s %s.", buf, mon_nam(mdef));
  362.     }
  363.  
  364.     if (!mdef->mcansee || mdef->msleep) {
  365.         if(vis) pline("but nothing happens.");
  366.         return(MM_MISS);
  367.     }
  368.  
  369.     return(mdamagem(magr, mdef, mattk));
  370. }
  371.  
  372. /* Returns the same values as mattackm(). */
  373. static int
  374. gulpmm(magr, mdef, mattk)
  375.     register struct monst *magr, *mdef;
  376.     register struct    attack *mattk;
  377. {
  378.     xchar    ax, ay, dx, dy;
  379.     int    status;
  380.     char buf[BUFSZ];
  381.  
  382.     if (mdef->data->msize >= MZ_HUGE) return MM_MISS;
  383.  
  384.     if (vis) {
  385.         Sprintf(buf,"%s swallows", Monnam(magr));
  386.         pline("%s %s.", buf, mon_nam(mdef));
  387.     }
  388.  
  389.     /*
  390.      *  All of this maniuplation is needed to keep the display correct.
  391.      *  There is a flush at the next pline().
  392.      */
  393.     ax = magr->mx;
  394.     ay = magr->my;
  395.     dx = mdef->mx;
  396.     dy = mdef->my;
  397.     /*
  398.      *  Leave the defender in the monster chain at it's current position,
  399.      *  but don't leave it on the screen.  Move the agressor to the def-
  400.      *  ender's position.
  401.      */
  402.     remove_monster(ax, ay);
  403.     place_monster(magr, dx, dy);
  404.     newsym(ax,ay);            /* erase old position */
  405.     newsym(dx,dy);            /* update new position */
  406.  
  407.     status = mdamagem(magr, mdef, mattk);
  408.  
  409.     if ((status & MM_AGR_DIED) && (status & MM_DEF_DIED)) {
  410.         ;                    /* both died -- do nothing  */
  411.     }
  412.     else if (status & MM_DEF_DIED) {    /* defender died */
  413.         /*
  414.          *  Note:  remove_monster() was called in relmon(), wiping out
  415.          *  magr from level.monsters[mdef->mx][mdef->my].  We need to
  416.          *  put it back and display it.    -kd
  417.          */
  418.         place_monster(magr, dx, dy);
  419.         newsym(dx, dy);
  420.     }
  421.     else if (status & MM_AGR_DIED) {    /* agressor died */
  422.         place_monster(mdef, dx, dy);
  423.         newsym(dx, dy);
  424.     }
  425.     else {                    /* both alive, put them back */
  426.         if (cansee(dx, dy))
  427.         pline("%s is regurgitated!", Monnam(mdef));
  428.  
  429.         place_monster(magr, ax, ay);
  430.         place_monster(mdef, dx, dy);
  431.         newsym(ax, ay);
  432.         newsym(dx, dy);
  433.     }
  434.  
  435.     return status;
  436. }
  437.  
  438. static int
  439. explmm(magr, mdef, mattk)
  440.     register struct monst *magr, *mdef;
  441.     register struct    attack *mattk;
  442. {
  443.     int result, was_tame;
  444.  
  445.     if(cansee(magr->mx, magr->my))
  446.         pline("%s explodes!", Monnam(magr));
  447.     else    noises(magr, mattk);
  448.  
  449.     was_tame = magr->mtame;
  450.     result = mdamagem(magr, mdef, mattk);
  451.  
  452.     /* The attacker could have died . . */
  453.     if (was_tame)
  454.         You("have a sad feeling for a moment, then it passes.");
  455.  
  456.     /* Kill off agressor if it didn't die. */
  457.     if (!(result & MM_AGR_DIED)) {
  458.         mondead(magr);
  459.         result |= MM_AGR_DIED;
  460.     }
  461.  
  462.     return result;
  463. }
  464.  
  465. static const char psf[] =
  466.     "have a peculiarly sad feeling for a moment, then it passes.";
  467.  
  468. /*
  469.  *  See comment at top of mattackm(), for return values.
  470.  */
  471. static int
  472. mdamagem(magr, mdef, mattk)
  473.     register struct monst    *magr, *mdef;
  474.     register struct attack    *mattk;
  475. {
  476.     struct    permonst *pa = magr->data, *pd = mdef->data;
  477.     int    tmp = d((int)mattk->damn,(int)mattk->damd);
  478.     char buf[BUFSZ];
  479.  
  480.     if (pd == &mons[PM_COCKATRICE] && !resists_ston(pa) &&
  481.        (mattk->aatyp != AT_WEAP || !otmp) &&
  482.        (mattk->aatyp != AT_GAZE && mattk->aatyp != AT_EXPL) &&
  483. #ifdef MUSE
  484.        (!which_armor(magr, W_ARMG))) {
  485. #else
  486.        (!is_mercenary(pa) || !m_carrying(magr, LEATHER_GLOVES))) {
  487.        /* Note: other monsters may carry gloves, only soldiers have them */
  488.        /* as their "armor" and can be said to wear them */
  489. #endif
  490.         if (poly_when_stoned(pa)) {
  491.             mon_to_stone(magr);
  492.             return MM_HIT; /* no damage during the polymorph */
  493.         }
  494.         if (vis) pline("%s turns to stone!", Monnam(magr));
  495.         else if (magr->mtame) You(psf);
  496.         monstone(magr);
  497.         return MM_AGR_DIED;
  498.     }
  499.  
  500.     switch(mattk->adtyp) {
  501.         case AD_DGST:
  502.         if(flags.verbose && flags.soundok) verbalize("Burrrrp!");
  503.         tmp = mdef->mhp;
  504.         break;
  505.         case AD_STUN:
  506.         if (magr->mcan) break;
  507.         if(vis) pline("%s staggers for a moment.", Monnam(mdef));
  508.         mdef->mstun = 1;
  509.         /* fall through */
  510.         case AD_WERE:
  511.         case AD_HEAL:
  512.         case AD_LEGS:
  513.         case AD_PHYS:
  514.         if (mattk->aatyp == AT_KICK && thick_skinned(pd))
  515.             tmp = 0;
  516.         else if(mattk->aatyp == AT_WEAP) {
  517.             if(otmp) {
  518.             tmp += dmgval(otmp, pd);
  519.             if (otmp->oartifact) {
  520.                 (void)artifact_hit(magr,mdef, otmp, &tmp, dieroll);
  521.                 if (mdef->mhp <= 0)
  522.                 return (MM_DEF_DIED |
  523.                     (grow_up(magr,mdef) ? 0 : MM_AGR_DIED));
  524.             }
  525.             if (tmp)
  526.                 mrustm(magr, mdef, otmp);
  527.             }
  528.         }
  529.         break;
  530.         case AD_FIRE:
  531.         if (magr->mcan) {
  532.             tmp = 0;
  533.             break;
  534.         }
  535.         if(vis) pline("%s is on fire!", Monnam(mdef));
  536.         tmp += destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE);
  537.         tmp += destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE);
  538.         if(resists_fire(pd)) {
  539.             if (vis)
  540.             pline("The fire doesn't seem to burn %s!",
  541.                                 mon_nam(mdef));
  542.             shieldeff(mdef->mx, mdef->my);
  543.             golemeffects(mdef, AD_FIRE, tmp);
  544.             tmp = 0;
  545.         }
  546.         /* only potions damage resistant players in destroy_item */
  547.         tmp += destroy_mitem(mdef, POTION_CLASS, AD_FIRE);
  548.         break;
  549.         case AD_COLD:
  550.         if (magr->mcan) {
  551.             tmp = 0;
  552.             break;
  553.         }
  554.         if(vis) pline("%s is covered in frost!", Monnam(mdef));
  555.         if(resists_cold(pd)) {
  556.             if (vis)
  557.             pline("The frost doesn't seem to chill %s!",
  558.                                 mon_nam(mdef));
  559.             shieldeff(mdef->mx, mdef->my);
  560.             golemeffects(mdef, AD_COLD, tmp);
  561.             tmp = 0;
  562.         }
  563.         tmp += destroy_mitem(mdef, POTION_CLASS, AD_COLD);
  564.         break;
  565.         case AD_ELEC:
  566.         if (magr->mcan) {
  567.             tmp = 0;
  568.             break;
  569.         }
  570.         if(vis) pline("%s gets zapped!", Monnam(mdef));
  571.         tmp += destroy_mitem(mdef, WAND_CLASS, AD_ELEC);
  572.         if(resists_elec(pd)) {
  573.             if (vis) pline("The zap doesn't shock %s!", mon_nam(mdef));
  574.             shieldeff(mdef->mx, mdef->my);
  575.             golemeffects(mdef, AD_ELEC, tmp);
  576.             tmp = 0;
  577.         }
  578.         /* only rings damage resistant players in destroy_item */
  579.         tmp += destroy_mitem(mdef, RING_CLASS, AD_ELEC);
  580.         break;
  581.         case AD_ACID:
  582.         if (magr->mcan) {
  583.             tmp = 0;
  584.             break;
  585.         }
  586.         if(resists_acid(pd)) {
  587.             if (vis)
  588.             pline("%s is covered in acid, but it seems harmless.",
  589.                             Monnam(mdef));
  590.             tmp = 0;
  591.         } else if (vis) {
  592.             pline("%s is covered in acid!", Monnam(mdef));
  593.             pline("It burns %s!", mon_nam(mdef));
  594.         }
  595.         break;
  596.         case AD_RUST:
  597.         if (!magr->mcan && pd == &mons[PM_IRON_GOLEM]) {
  598.             if (vis) pline("%s falls to pieces!", Monnam(mdef));
  599.             else if(mdef->mtame)
  600.                  pline("May %s rust in peace.", mon_nam(mdef));
  601.             mondied(mdef);
  602.             return (MM_DEF_DIED | (grow_up(magr,mdef) ?
  603.                             0 : MM_AGR_DIED));
  604.         }
  605.         tmp = 0;
  606.         break;
  607.         case AD_DCAY:
  608.         if (!magr->mcan && (pd == &mons[PM_WOOD_GOLEM] ||
  609.             pd == &mons[PM_LEATHER_GOLEM])) {
  610.             if (vis) pline("%s falls to pieces!", Monnam(mdef));
  611.             else if(mdef->mtame)
  612.                  pline("May %s rot in peace.", mon_nam(mdef));
  613.             mondied(mdef);
  614.             return (MM_DEF_DIED | (grow_up(magr,mdef) ?
  615.                             0 : MM_AGR_DIED));
  616.         }
  617.         tmp = 0;
  618.         break;
  619.         case AD_STON:
  620.         if(poly_when_stoned(pd)) {
  621.             mon_to_stone(mdef);
  622.             tmp = 0;
  623.             break;
  624.         }
  625.         if(!resists_ston(pd)) {
  626.             if(vis) pline("%s turns to stone!", Monnam(mdef));
  627.             else if(mdef->mtame) You(psf);
  628.             monstone(mdef);
  629.             return (MM_DEF_DIED | (grow_up(magr,mdef) ?
  630.                             0 : MM_AGR_DIED));
  631.         }
  632.         tmp = 0;    /* no damage if this fails */
  633.         break;
  634.         case AD_TLPT:
  635.         if(!magr->mcan && tmp < mdef->mhp) {
  636.             rloc(mdef);
  637.             if(vis && !cansee(mdef->mx, mdef->my))
  638.             pline("%s suddenly disappears!", Monnam(mdef));
  639.         }
  640.         break;
  641.         case AD_SLEE:
  642.         if(!resists_sleep(pd) && !magr->mcan && !mdef->msleep
  643.                             && mdef->mcanmove) {
  644.             if (vis) {
  645.             Strcpy(buf, Monnam(mdef));
  646.             pline("%s is put to sleep by %s.", buf, mon_nam(magr));
  647.             }
  648.             mdef->mcanmove = 0;
  649.             mdef->mfrozen = rnd(10);
  650.         }
  651.         break;
  652.         case AD_PLYS:
  653.         if(!magr->mcan && mdef->mcanmove) {
  654.             if (vis) {
  655.             Strcpy(buf, Monnam(mdef));
  656.             pline("%s is frozen by %s.", buf, mon_nam(magr));
  657.             }
  658.             mdef->mcanmove = 0;
  659.             mdef->mfrozen = rnd(10);
  660.         }
  661.         break;
  662.         case AD_SLOW:
  663.         if(!magr->mcan && vis && mdef->mspeed != MSLOW) {
  664.             if (vis) pline("%s slows down.", Monnam(mdef));
  665.             if (mdef->mspeed == MFAST) mdef->mspeed = 0;
  666.             else mdef->mspeed = MSLOW;
  667.         }
  668.         break;
  669.         case AD_CONF:
  670.         /* Since confusing another monster doesn't have a real time
  671.          * limit, setting spec_used would not really be right (though
  672.          * we still should check for it).
  673.          */
  674.         if (!magr->mcan && vis && !mdef->mconf && !magr->mspec_used) {
  675.             pline("%s looks confused.", Monnam(mdef));
  676.             mdef->mconf = 1;
  677.         }
  678.         break;
  679.         case AD_BLND:
  680.         if (!magr->mcan && haseyes(pd)) {
  681.             register unsigned rnd_tmp;
  682.  
  683.             if (vis && mdef->mcansee)
  684.             pline("%s is blinded.", Monnam(mdef));
  685.             rnd_tmp = d((int)mattk->damn, (int)mattk->damd);
  686.             if ((rnd_tmp += mdef->mblinded) > 127) rnd_tmp = 127;
  687.             mdef->mblinded = rnd_tmp;
  688.             mdef->mcansee = 0;
  689.         }
  690.         tmp = 0;
  691.         break;
  692.         case AD_CURS:
  693.         if (!night() && (pa == &mons[PM_GREMLIN])) break;
  694.         if (!magr->mcan && !rn2(10)) {
  695.             if (is_were(pd) && pd->mlet != S_HUMAN)
  696.             were_change(mdef);
  697.             if (pd == &mons[PM_CLAY_GOLEM]) {
  698.                 if (vis) {
  699.                 pline("Some writing vanishes from %s head!",
  700.                     s_suffix(mon_nam(mdef)));
  701.                 pline("%s dies!", Monnam(mdef));
  702.                 }
  703.                 else if (mdef->mtame)
  704.     You("have a strangely sad feeling for a moment, then it passes.");
  705.                 mondied(mdef);
  706.                 return (MM_DEF_DIED | (grow_up(magr,mdef) ?
  707.                             0 : MM_AGR_DIED));
  708.               }
  709.             mdef->mcan = 1;
  710.             if (flags.soundok) {
  711.                 if (!vis) You("hear laughter.");
  712.                 else pline("%s chuckles.", Monnam(magr));
  713.             }
  714.         }
  715.         break;
  716.         case AD_SGLD:
  717.         tmp = 0;
  718.         if (magr->mcan || !mdef->mgold) break;
  719.         /* technically incorrect; no check for stealing gold from
  720.          * between mdef's feet...
  721.          */
  722.         magr->mgold += mdef->mgold;
  723.         mdef->mgold = 0;
  724.         if (vis) {
  725.             Strcpy(buf, Monnam(magr));
  726.             pline("%s steals some gold from %s.", buf,
  727.                                 mon_nam(mdef));
  728.         }
  729.         break;
  730.         case AD_DRLI:
  731.         if(rn2(2) && !resists_drli(pd)) {
  732.             tmp = d(2,6);
  733.             if (vis)
  734.                 pline("%s suddenly seems weaker!", Monnam(mdef));
  735.             mdef->mhpmax -= tmp;
  736.             if (mdef->m_lev == 0)
  737.                 tmp = mdef->mhp;
  738.             else mdef->m_lev--;
  739.             /* Automatic kill if drained past level 0 */
  740.         }
  741.         break;
  742. #ifdef SEDUCE
  743.         case AD_SSEX:
  744. #endif
  745.         case AD_SITM:    /* for now these are the same */
  746.         case AD_SEDU:
  747.         if (!magr->mcan && mdef->minvent) {
  748.                otmp = mdef->minvent;
  749.             mdef->minvent = otmp->nobj;
  750.             otmp->nobj = magr->minvent;
  751.             magr->minvent = otmp;
  752.             if (vis) {
  753.                 Strcpy(buf, Monnam(magr));
  754.                 pline("%s steals %s from %s!", buf,
  755.                         doname(otmp), mon_nam(mdef));
  756.             }
  757. #ifdef MUSE
  758.             possibly_unwield(mdef);
  759.             if (otmp->owornmask) {
  760.                 mdef->misc_worn_check &= ~otmp->owornmask;
  761.                 otmp->owornmask = 0;
  762.             }
  763. #endif
  764.         }
  765.         tmp = 0;
  766.         break;
  767.         case AD_DRST:
  768.         case AD_DRDX:
  769.         case AD_DRCO:
  770.         if (!magr->mcan && !rn2(8)) {
  771.             if (vis)
  772.             pline("%s %s was poisoned!", s_suffix(Monnam(magr)),
  773.                 mattk->aatyp==AT_BITE ? "bite" : "sting");
  774.             if (resists_poison(pd)) {
  775.             if (vis)
  776.                 pline("The poison doesn't seem to affect %s.",
  777.                 mon_nam(mdef));
  778.             } else {
  779.             if (rn2(10)) tmp += rn1(10,6);
  780.             else {
  781.                 if (vis) pline("The poison was deadly...");
  782.                 tmp = mdef->mhp;
  783.             }
  784.             }
  785.         }
  786.         break;
  787.         case AD_DRIN:
  788.         if (!has_head(pd)) {
  789.             if (vis) pline("%s doesn't seem harmed.", Monnam(mdef));
  790.             tmp = 0;
  791.             break;
  792.         }
  793. #ifdef MUSE
  794.         if ((mdef->misc_worn_check & W_ARMH) && rn2(8)) {
  795.             if (vis) {
  796.             Strcpy(buf, s_suffix(Monnam(mdef)));
  797.             pline("%s helmet blocks %s attack to his head.",
  798.                 buf, s_suffix(mon_nam(magr)));
  799.             }
  800.             break;
  801.         }
  802. #endif
  803.         if (vis) pline("%s brain is eaten!", s_suffix(Monnam(mdef)));
  804.         if (mindless(pd)) {
  805.             if (vis) pline("%s doesn't notice.", Monnam(mdef));
  806.             break;
  807.         }
  808.         tmp += rnd(10); /* fakery, since monsters lack INT scores */
  809.         if (magr->mtame && !magr->isminion) {
  810.             EDOG(magr)->hungrytime += rnd(60);
  811.             magr->mconf = 0;
  812.         }
  813.         if (tmp >= mdef->mhp && vis)
  814.             pline("%s last thought fades away...", 
  815.                       s_suffix(Monnam(mdef)));
  816.         break;
  817.         case AD_STCK:
  818.         case AD_WRAP: /* monsters cannot grab one another, it's too hard */
  819.         break;
  820.         default:    tmp = 0;
  821.             break;
  822.     }
  823.     if(!tmp) return(MM_MISS);
  824.  
  825.     if((mdef->mhp -= tmp) < 1) {
  826.         if (m_at(mdef->mx, mdef->my) == magr) {  /* see gulpmm() */
  827.         remove_monster(mdef->mx, mdef->my);
  828.         place_monster(mdef, mdef->mx, mdef->my);
  829.         }
  830.         monkilled(mdef, "", mattk->adtyp);
  831.         return (MM_DEF_DIED | (grow_up(magr,mdef) ? 0 : MM_AGR_DIED));
  832.     }
  833.     return(MM_HIT);
  834. }
  835.  
  836. #endif /* OVLB */
  837.  
  838.  
  839. #ifdef OVL0
  840.  
  841. int
  842. noattacks(ptr)            /* returns 1 if monster doesn't attack */
  843.     struct    permonst *ptr;
  844. {
  845.     int i;
  846.  
  847.     for(i = 0; i < NATTK; i++)
  848.         if(ptr->mattk[i].aatyp) return(0);
  849.  
  850.     return(1);
  851. }
  852.  
  853. #endif /* OVL0 */
  854. #ifdef OVLB
  855.  
  856. static void
  857. mrustm(magr, mdef, obj)
  858. register struct monst *magr, *mdef;
  859. register struct obj *obj;
  860. {
  861.     if (!magr || !mdef || !obj) return; /* just in case */
  862.     if (mdef->data == &mons[PM_RUST_MONSTER] && !mdef->mcan &&
  863.         is_rustprone(obj) && obj->oeroded < MAX_ERODE) {
  864.         if (obj->greased || obj->oerodeproof || (obj->blessed && rn2(3))) {
  865.             if (cansee(mdef->mx, mdef->my) && flags.verbose)
  866.             pline("%s weapon is not affected.", 
  867.                              s_suffix(Monnam(magr)));
  868.             if (obj->greased && !rn2(2)) obj->greased = 0;
  869.         } else {
  870.             if (cansee(mdef->mx, mdef->my)) {
  871.             pline("%s %s%s!", s_suffix(Monnam(magr)),
  872.                   aobjnam(obj, "rust"),
  873.                   obj->oeroded ? " further" : "");
  874.             }
  875.             obj->oeroded++;
  876.         }
  877.     }
  878. }
  879.  
  880. static void
  881. mswingsm(magr, mdef, otemp)
  882. register struct monst *magr, *mdef;
  883. register struct obj *otemp;
  884. {
  885.     char buf[BUFSZ];
  886.     Strcpy(buf, mon_nam(mdef));
  887.     if (!flags.verbose || Blind || otemp->oclass != WEAPON_CLASS) return;
  888.     pline("%s %s %s %s at %s.", Monnam(magr),
  889.           ((otemp->otyp >= SPEAR &&
  890.             otemp->otyp <= LANCE) ||
  891.            (otemp->otyp >= PARTISAN &&
  892.             otemp->otyp <= SPETUM) ||
  893.            otemp->otyp == TRIDENT) ? "thrusts" : "swings",
  894.           humanoid(magr->data) ? (magr->female ? "her" : "his") : "its",
  895.           xname(otemp), buf);
  896. }
  897.  
  898. /*
  899.  * Passive responses by defenders.  Does not replicate responses already
  900.  * handled above.  Returns same values as mattackm.
  901.  */
  902. static int
  903. passivemm(magr,mdef,mhit,mdead)
  904. register struct monst *magr, *mdef;
  905. boolean mhit;
  906. int mdead;
  907. {
  908.     register struct permonst *mddat = mdef->data;
  909.     register struct permonst *madat = magr->data;
  910.     char buf[BUFSZ];
  911.     int i, tmp;
  912.  
  913.     for(i = 0; ; i++) {
  914.         if(i >= NATTK) return (mdead | mhit); /* no passive attacks */
  915.         if(mddat->mattk[i].aatyp == AT_NONE) break;
  916.     }
  917.     if (mddat->mattk[i].damn)
  918.         tmp = d((int)mddat->mattk[i].damn, 
  919.                                     (int)mddat->mattk[i].damd);
  920.     else if(mddat->mattk[i].damd)
  921.         tmp = d((int)mddat->mlevel+1, (int)mddat->mattk[i].damd);
  922.     else
  923.         tmp = 0;
  924.  
  925.     /* These affect the enemy even if defender killed */
  926.     switch(mddat->mattk[i].adtyp) {
  927.         case AD_ACID:
  928.         if (mhit && !rn2(2)) {
  929.             Strcpy(buf, Monnam(magr));
  930.             if(canseemon(magr))
  931.             pline("%s is splashed by %s acid!",
  932.                   buf, s_suffix(mon_nam(mdef)));
  933.             if(resists_acid(madat)) {
  934.             if(canseemon(magr))
  935.                 pline("%s is not affected.", Monnam(magr));
  936.             tmp = 0;
  937.             }
  938.         } else tmp = 0;
  939.         goto assess_dmg;
  940.         default:
  941.         break;
  942.     }
  943.     if (mdead || mdef->mcan) return (mdead|mhit);
  944.  
  945.     /* These affect the enemy only if defender is still alive */
  946.     if (rn2(3)) switch(mddat->mattk[i].adtyp) {
  947.         case AD_PLYS: /* Floating eye */
  948.         if (mddat == &mons[PM_FLOATING_EYE]) {
  949.             if (magr->mcansee && haseyes(madat) && mdef->mcansee &&
  950.             (perceives(madat) || !mdef->minvis)) {
  951.             Strcpy(buf, Monnam(magr));
  952.             if(canseemon(magr))
  953.                 pline("%s is frozen by %s gaze!",
  954.                   buf, s_suffix(mon_nam(mdef)));
  955.             magr->mcanmove = 0;
  956.             magr->mfrozen = tmp;
  957.             return (mdead|mhit);
  958.             }
  959.         } else { /* gelatinous cube */
  960.             Strcpy(buf, Monnam(magr));
  961.             if(canseemon(magr))
  962.             pline("%s is frozen by %s.", buf, mon_nam(mdef));
  963.             magr->mcanmove = 0;
  964.             magr->mfrozen = tmp;
  965.             return (mdead|mhit);
  966.         }
  967.         return 1;
  968.         case AD_COLD:
  969.         if (resists_cold(madat)) {
  970.             if (canseemon(magr)) {
  971.             pline("%s is mildly chilly.", Monnam(magr));
  972.             golemeffects(magr, AD_COLD, tmp);
  973.             tmp = 0;
  974.             break;
  975.             }
  976.         }
  977.         if(canseemon(magr))
  978.             pline("%s is suddenly very cold!", Monnam(magr));
  979.         mdef->mhp += tmp / 2;
  980.         if (mdef->mhpmax < mdef->mhp) mdef->mhpmax = mdef->mhp;
  981.         if (mdef->mhpmax > ((int) (mdef->m_lev+1) * 8)) {
  982.             register struct monst *mtmp;
  983.  
  984.             if ((mtmp = clone_mon(mdef)) != 0) {
  985.             mtmp->mhpmax = mdef->mhpmax /= 2;
  986.             if(canseemon(magr)) {
  987.                 Strcpy(buf, Monnam(mdef));
  988.                 pline("%s multiplies from %s heat!",
  989.                     buf, s_suffix(mon_nam(magr)));
  990.             }
  991.             }
  992.         }
  993.         break;
  994.         case AD_STUN:
  995.         if (!magr->mstun) {
  996.             magr->mstun = 1;
  997.             if (canseemon(magr))
  998.             pline("%s staggers....", Monnam(magr));
  999.         }
  1000.         tmp = 0;
  1001.         break;
  1002.         case AD_FIRE:
  1003.         if (resists_fire(madat)) {
  1004.             if (canseemon(magr)) {
  1005.             pline("%s is mildly warmed.", Monnam(magr));
  1006.             golemeffects(magr, AD_FIRE, tmp);
  1007.             tmp = 0;
  1008.             break;
  1009.             }
  1010.         }
  1011.         if(canseemon(magr))
  1012.             pline("%s is suddenly very hot!", Monnam(magr));
  1013.         break;
  1014.         case AD_ELEC:
  1015.         if (resists_elec(madat)) {
  1016.             if (canseemon(magr)) {
  1017.             pline("%s is mildly tingled.", Monnam(magr));
  1018.             golemeffects(magr, AD_ELEC, tmp);
  1019.             tmp = 0;
  1020.             break;
  1021.             }
  1022.         }
  1023.         if(canseemon(magr))
  1024.             pline("%s is jolted with electricity!", Monnam(magr));
  1025.         break;
  1026.         default: tmp = 0;
  1027.         break;
  1028.     }
  1029.     else tmp = 0;
  1030.  
  1031.     assess_dmg:
  1032.     if((magr->mhp -= tmp) <= 0) {
  1033.         monkilled(magr,"",mddat->mattk[i].adtyp);
  1034.         return (mdead | mhit | MM_AGR_DIED);
  1035.     }
  1036.     return (mdead | mhit);
  1037. }
  1038.  
  1039. #endif /* OVLB */
  1040.  
  1041. /*mhitm.c*/
  1042.